package com.fitzone.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fitzone.common.exception.BaseException;
import com.fitzone.model.dto.CourseDTO;
import com.fitzone.model.dto.CourseMiniDTO;
import com.fitzone.model.entity.*;
import com.fitzone.model.vo.CourseMiniInfoVO;
import com.fitzone.model.vo.CourseMiniVO;
import com.fitzone.model.vo.CourseVO;
import com.fitzone.web.mapper.*;
import com.fitzone.web.service.CourseService;
import org.aspectj.weaver.ast.Or;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private CoachMapper coachMapper;
    @Autowired
    private StoreMapper storeMapper;
    @Autowired
    private BannerMapper bannerMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrdersMapper ordersMapper;

    /**
     * 添加课程
     * @param courseDTO
     */
    @Override
    public void saveCourse(CourseDTO courseDTO) {
        Course course = new Course();
        if (courseDTO.getStartTime().isBefore(LocalDateTime.now())){
            throw new BaseException("开始时间不能在当前时间之前");
        }
        if (courseDTO.getStartTime().isAfter(courseDTO.getEndTime())){
            throw new BaseException("开始时间不能在结束时间之后");
        }
        BeanUtils.copyProperties(courseDTO, course);
        course.setStatus(0);
        this.save(course);
    }

    /**
     * 修改课程
     * @param courseDTO
     */
    @Override
    public void updateCourse(CourseDTO courseDTO) {
        Course course = new Course();
        if (courseDTO.getStartTime().isBefore(LocalDateTime.now())){
            throw new BaseException("开始时间不能在当前时间之前");
        }
        if (courseDTO.getStartTime().isAfter(courseDTO.getEndTime())){
            throw new BaseException("开始时间不能在结束时间之后");
        }
        BeanUtils.copyProperties(courseDTO,course);
        this.updateById(course);
    }

    /**
     * 根据课程id查询课程
     * @param id
     * @return
     */
    @Override
    public CourseVO getId(Long id) {
        Course course = courseMapper.selectById(id);
        CourseVO courseVO = new CourseVO();
        BeanUtils.copyProperties(course, courseVO);
        Coach coach = coachMapper.selectById(course.getCoachId());
        courseVO.setCoachName(coach.getCoachName());
        Store store = storeMapper.selectById(course.getStoreId());
        courseVO.setStoreName(store.getStoreName());
        return courseVO;
    }

    /**
     * 课程列表
     * @param courseMiniDTO
     * @return
     */
    @Override
    public List<CourseMiniVO> courseList(CourseMiniDTO courseMiniDTO) {
        LambdaQueryWrapper<Store> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(courseMiniDTO.getCity() != null, Store::getCity, courseMiniDTO.getCity())
                .eq(courseMiniDTO.getStoreName() != null, Store::getStoreName, courseMiniDTO.getStoreName());
        List<Store> stores = storeMapper.selectList(queryWrapper1);
        ArrayList<CourseMiniVO> list = new ArrayList<>();
        for (Store store : stores) {
            CourseMiniVO courseMiniVO = new CourseMiniVO();
            BeanUtils.copyProperties(store, courseMiniVO);
            // 查询与当前店铺相关的课程
            LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Course::getStoreId, store.getId());
            List<Course> courses = courseMapper.selectList(queryWrapper);
            for (Course course : courses) {
                LambdaQueryWrapper<Orders> queryWrapper2 = new LambdaQueryWrapper<>();
                queryWrapper2.eq(course.getId() != null,Orders::getCourseId, course.getId());
                Integer count = ordersMapper.selectCount(queryWrapper2);
                course.setCount(count);
                Coach coach = coachMapper.selectById(course.getCoachId());
                course.setCoachName(coach.getCoachName());
            }

            // 将课程列表设置给当前店铺
            courseMiniVO.setCourseList(courses);
            list.add(courseMiniVO);
        }
        return list;
    }

    /**
     * 课程详情
     * @param courseId
     * @return
     */
    @Override
    public CourseMiniInfoVO courseInfoById(Long courseId) {
        LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Course::getId,courseId);
        List<Course> courses = courseMapper.selectList(queryWrapper);

        CourseMiniInfoVO courseMiniInfoVO = new CourseMiniInfoVO();
        for (Course course : courses) {
            Coach coach = coachMapper.selectById(course.getCoachId());

            Store store = storeMapper.selectById(course.getStoreId());

            courseMiniInfoVO.setCity(store.getCity());
            courseMiniInfoVO.setAddress(store.getAddress());
            courseMiniInfoVO.setStoreName(store.getStoreName());

            courseMiniInfoVO.setCoachName(coach.getCoachName());

            courseMiniInfoVO.setDetail(course.getCourseDesc());
            courseMiniInfoVO.setCourseName(course.getCourseName());
            courseMiniInfoVO.setStartTime(course.getStartTime());
            courseMiniInfoVO.setEndTime(course.getEndTime());
            courseMiniInfoVO.setStatus(course.getStatus());

            LambdaQueryWrapper<Banner> bannerQueryWrapper = new LambdaQueryWrapper<>();
            bannerQueryWrapper.eq(Banner::getCourseId,course.getId());
            List<Banner> banners = bannerMapper.selectList(bannerQueryWrapper);

            ArrayList<Map<String, Object>> bannerList = new ArrayList<>();
            for (Banner banner : banners) {
                HashMap<String, Object> bannerMap = new HashMap<>();
                bannerMap.put("bannerImg",banner.getUrl());
                bannerMap.put("bannerId",banner.getId());
                bannerList.add(bannerMap);
            }
            courseMiniInfoVO.setBannerList(bannerList);

            ArrayList<Map<String, Object>> userList = new ArrayList<>();
            LambdaQueryWrapper<Orders> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(Orders::getCourseId,courseId);
            List<Orders> orders = ordersMapper.selectList(queryWrapper1);
            for (Orders order : orders) {
                LambdaQueryWrapper<User> queryWrapper2 = new LambdaQueryWrapper<>();
                queryWrapper2.eq(User::getId,order.getUserId());
                List<User> users = userMapper.selectList(queryWrapper2);
                for (User user : users) {
                    HashMap<String, Object> userMap = new HashMap<>();
                    userMap.put("userId",user.getId());
                    userMap.put("userImg",user.getAvatar());
                    userList.add(userMap);
                }
            }
            courseMiniInfoVO.setUserList(userList);
        }
        return courseMiniInfoVO;
    }

    @Override
    @Transactional
    public int publishCourse(Long id) {
        Course course = courseMapper.selectById(id);
        course.setStatus(1);
        courseMapper.updateById(course);
        // 开始定时任务，到时间后修改活动状态
        LocalDateTime now = LocalDateTime.now();
        long start = Duration.between(now, course.getStartTime()).getSeconds();
        long end = Duration.between(now, course.getEndTime()).getSeconds();

        long [] delays = {start,end};
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        int count = 0;
        for (int i = 0; i < delays.length; i++) {
            if (delays[i] < 0)
                continue;
            executor.schedule(() -> {
                updateStatus(id);
            }, delays[i] + 3, TimeUnit.SECONDS);
            count++;
        }
        return 0;
    }
    @Transactional
    public void updateStatus(Long id) {
        Course course = courseMapper.selectById(id);
        if (course.getStatus() == 3){
            throw new BaseException("课程已结束");
        }
        LocalDateTime now = LocalDateTime.now();
        if (now.compareTo(course.getStartTime()) >= 0)
            course.setStatus(2);
        if (now.compareTo(course.getEndTime()) >= 0)
            course.setStatus(3);

        courseMapper.updateById(course);
    }
}
